// +----------------------------------------------------------------------
// | ShopSuite商城系统 [ 赋能开发者，助力企业发展 ]
// +----------------------------------------------------------------------
// | 版权所有 随商信息技术（上海）有限公司
// +----------------------------------------------------------------------
// | 未获商业授权前，不得将本软件用于商业用途。禁止整体或任何部分基础上以发展任何派生版本、
// | 修改版本或第三方版本用于重新分发。
// +----------------------------------------------------------------------
// | 官方网站: https://www.shopsuite.cn  https://www.modulithshop.cn
// +----------------------------------------------------------------------
// | 版权和免责声明:
// | 本公司对该软件产品拥有知识产权（包括但不限于商标权、专利权、著作权、商业秘密等）
// | 均受到相关法律法规的保护，任何个人、组织和单位不得在未经本团队书面授权的情况下对所授权
// | 软件框架产品本身申请相关的知识产权，禁止用于任何违法、侵害他人合法权益等恶意的行为，禁
// | 止用于任何违反我国法律法规的一切项目研发，任何个人、组织和单位用于项目研发而产生的任何
// | 意外、疏忽、合约毁坏、诽谤、版权或知识产权侵犯及其造成的损失 (包括但不限于直接、间接、
// | 附带或衍生的损失等)，本团队不承担任何法律责任，本软件框架只能用于公司和个人内部的
// | 法律所允许的合法合规的软件产品研发，详细见https://www.modulithshop.cn/policy
// +----------------------------------------------------------------------
package com.suisung.shopsuite.pay.controller.front;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayRequest;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ijpay.alipay.AliPayApi;
import com.ijpay.core.IJPayHttpResponse;
import com.ijpay.core.enums.RequestMethodEnum;
import com.ijpay.core.kit.AesUtil;
import com.ijpay.core.kit.PayKit;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.core.utils.DateTimeZoneUtil;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.enums.WxDomainEnum;
import com.ijpay.wxpay.enums.v3.BasePayApiEnum;
import com.ijpay.wxpay.model.v3.*;
import com.suisung.shopsuite.account.model.entity.UserBindConnect;
import com.suisung.shopsuite.account.repository.UserBindConnectRepository;
import com.suisung.shopsuite.common.api.ResultCode;
import com.suisung.shopsuite.common.api.StateCode;
import com.suisung.shopsuite.common.auth.Auth;
import com.suisung.shopsuite.common.consts.BindConnectCode;
import com.suisung.shopsuite.common.consts.ConstantConfig;
import com.suisung.shopsuite.common.consts.ConstantLog;
import com.suisung.shopsuite.common.consts.ConstantPay;
import com.suisung.shopsuite.common.exception.BusinessException;
import com.suisung.shopsuite.common.pojo.dto.ErrorTypeEnum;
import com.suisung.shopsuite.common.pojo.dto.PayType;
import com.suisung.shopsuite.common.utils.*;
import com.suisung.shopsuite.common.web.ContextUser;
import com.suisung.shopsuite.core.web.CommonRes;
import com.suisung.shopsuite.core.web.controller.BaseController;
import com.suisung.shopsuite.pay.model.entity.ConsumeTrade;
import com.suisung.shopsuite.pay.model.entity.UserPay;
import com.suisung.shopsuite.pay.model.entity.UserResource;
import com.suisung.shopsuite.pay.model.input.PaymentInput;
import com.suisung.shopsuite.pay.model.output.PayOutput;
import com.suisung.shopsuite.pay.model.output.ProcessPayOutput;
import com.suisung.shopsuite.pay.model.req.PaymentReq;
import com.suisung.shopsuite.pay.model.res.*;
import com.suisung.shopsuite.pay.model.vo.AliPayVo;
import com.suisung.shopsuite.pay.model.vo.PayMetVo;
import com.suisung.shopsuite.pay.model.vo.WxPayV3Vo;
import com.suisung.shopsuite.pay.repository.ConsumeCombineRepository;
import com.suisung.shopsuite.pay.repository.ConsumeTradeRepository;
import com.suisung.shopsuite.pay.repository.UserPayRepository;
import com.suisung.shopsuite.pay.repository.UserResourceRepository;
import com.suisung.shopsuite.pay.service.ConsumeTradeService;
import com.suisung.shopsuite.sys.service.ConfigBaseService;
import io.swagger.annotations.Api;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.cert.X509Certificate;
import java.util.*;
import java.util.stream.Collectors;

import static com.suisung.shopsuite.common.utils.I18nUtil.__;
import static com.suisung.shopsuite.common.utils.UploadUtil.getUploadFileDir;

/**
 * <p>
 * 唤起支付
 * </p>
 *
 * @author Xinze
 * @since 2021-06-30
 */
@Api(tags = "唤起支付")
@RestController
@RequestMapping("/front/pay/consumeDeposit")
public class PaymentIndexController extends BaseController {

    @Autowired
    private ConsumeTradeRepository tradeRepository;

    @Autowired
    private ConfigBaseService configBaseService;

    @Autowired
    private ConsumeCombineRepository combineRepository;

    @Autowired
    private UserBindConnectRepository userBindConnectRepository;

    @Autowired
    private ConsumeTradeService consumeTradeService;

    @Autowired
    private UserResourceRepository userResourceRepository;

    @Autowired
    private UserPayRepository userPayRepository;


    private static final Logger logger = LoggerFactory.getLogger(PaymentIndexController.class);

    // 余额支付
    @RequestMapping(value = "/moneyPay", method = RequestMethod.POST)
    public CommonRes<?> money(@Auth ContextUser user, PaymentReq req) {
        Integer userId = ContextUtil.checkLoginUserId();

        req.setPaymentChannelId(StateCode.PAYMENT_MET_MONEY);
        req.setDepositPaymentType(StateCode.PAYMENT_TYPE_ONLINE);

        //处理订单支付结果
        PayMetVo payInfo = new PayMetVo();
        payInfo.setPaymentMetId(StateCode.PAYMENT_MET_MONEY);
        payInfo.setPaymentChannelId(req.getPaymentChannelId());
        payInfo.setPaymentTypeId(req.getDepositPaymentType());
        payInfo.setPmMoney(req.getPmMoney());

        MoneyPayRes res = new MoneyPayRes();
        res.setOrderId(req.getOrderId());

        //判断余额是否足够，不够报错！
        UserResource userResourceBuy = userResourceRepository.get(userId);
        if (userResourceBuy.getUserMoney().compareTo(payInfo.getPmMoney()) >= 0) {

            checkPayPasswd(user.getUserId(), req.getPassword());

            ProcessPayOutput processPayOutput = consumeTradeService.processPay(req.getOrderId(), payInfo);

            if (processPayOutput.getPaid()) {
                res.setPaid(processPayOutput.getPaid());
                res.setStatusCode(200);
            } else {
                res.setStatusCode(250);
            }

            return success(res);
        } else {
            res.setPaid(false);
            res.setStatusCode(250);

            return fail(res);
        }
    }

    /**
     * 验证支付密码
     *
     * @param userId
     * @param password
     * @return
     */
    public void checkPayPasswd(Integer userId, String password) {

        UserPay userPay = userPayRepository.get(userId);
        if (userPay != null && StrUtil.isNotBlank(userPay.getUserPayPasswd())) {

            String userPaySalt = userPay.getUserPaySalt();
            String saltPassword = SecureUtil.md5(userPaySalt + SecureUtil.md5(password));

            if (!StrUtil.equals(saltPassword, userPay.getUserPayPasswd())) {
                throw new BusinessException(__("支付密码错误！"));
            }
        } else {
            throw new BusinessException(ResultCode.PAY_PWD_FAILED);
        }
    }

    private String savePlatformCert(String associatedData, String nonce, String cipherText, String certPath) {
        try {
            AesUtil aesUtil = new AesUtil(configBaseService.getConfig("wechat_pay_v3_key").getBytes(StandardCharsets.UTF_8));
            // 平台证书密文解密
            // encrypt_certificate 中的  associated_data nonce  ciphertext
            String publicKey = aesUtil.decryptToString(
                    associatedData.getBytes(StandardCharsets.UTF_8),
                    nonce.getBytes(StandardCharsets.UTF_8),
                    cipherText
            );
            // 保存证书
            FileWriter writer = new FileWriter(certPath);
            writer.write(publicKey);
            // 获取平台证书序列号
            X509Certificate certificate = PayKit.getCertificate(new ByteArrayInputStream(publicKey.getBytes()));
            return certificate.getSerialNumber().toString(16).toUpperCase();
        } catch (Exception e) {
            LogUtil.error(ConstantLog.PAY, e);
            return e.getMessage();
        }
    }

    @RequestMapping("/get")
    public String v3Get() {
//        File file = new File(getUploadFileDir(), "wx_cert.pem");
//        String platformCertPath = file.getAbsolutePath();
//
//        // 获取平台证书列表
//        try {
//            IJPayHttpResponse response = WxPayApi.v3(
//                    RequestMethodEnum.GET,
//                    WxDomainEnum.CHINA.toString(),
//                    OtherApiEnum.GET_CERTIFICATES.toString(),
//                    configBaseService.getConfig("wechat_pay_mchid"),
//                    getSerialNumber(),
//                    null,
//                    configBaseService.getConfig("wechat_pay_apiclient_key"),
//                    ""
//            );
//
//            String timestamp = response.getHeader("Wechatpay-Timestamp");
//            String nonceStr = response.getHeader("Wechatpay-Nonce");
//            String serialNumber = response.getHeader("Wechatpay-Serial");
//            String signature = response.getHeader("Wechatpay-Signature");
//
//            String body = response.getBody();
//            int status = response.getStatus();
//
//            logger.info("serialNumber: {}", serialNumber);
//            logger.info("status: {}", status);
//            logger.info("body: {}", body);
//            int isOk = 200;
//            if (status == isOk) {
//                JSONObject jsonObject = JSONUtil.parseObj(body);
//                JSONArray dataArray = jsonObject.getJSONArray("data");
//                // 默认认为只有一个平台证书
//                JSONObject encryptObject = dataArray.getJSONObject(0);
//                JSONObject encryptCertificate = encryptObject.getJSONObject("encrypt_certificate");
//                String associatedData = encryptCertificate.getStr("associated_data");
//                String cipherText = encryptCertificate.getStr("ciphertext");
//                String nonce = encryptCertificate.getStr("nonce");
//                String serialNo = encryptObject.getStr("serial_no");
//                final String platSerialNo = savePlatformCert(associatedData, nonce, cipherText, platformCertPath);
//                logger.info("平台证书序列号: {} serialNo: {}", platSerialNo, serialNo);
//            }
//            // 根据证书序列号查询对应的证书来验证签名结果
//            boolean verifySignature = WxPayKit.verifySignature(response, platformCertPath);
//            System.out.println("verifySignature:" + verifySignature);
//            return body;
//        } catch (Exception e) {
//            LogUtil.error(ConstantLog.PAY, e);
//            return null;
//        }
        return null;
    }

    @RequestMapping(value = "/wechatNativePay", method = RequestMethod.POST)
    public CommonRes<WechatNativePayRes> wechatNativePay(PaymentReq req) {
        WxPayV3Vo wxPayV3Vo = configBaseService.getWxPayV3Vo();
        //weixin_app_id
        String appId = configBaseService.getConfig("wechat_app_id");
        wxPayV3Vo.setAppId(appId);

        req.setPaymentChannelId(StateCode.PAYMENT_CHANNEL_WECHAT);

        PayOutput output = getPayResult(req);

        WechatNativePayRes wechatNativePayRes = new WechatNativePayRes();
        wechatNativePayRes.setOrderId(req.getOrderId());
        wechatNativePayRes.setPaymentAmount(Convert.toBigDecimal(output.getAmount()).divide(BigDecimal.valueOf(100)));

        try {
            String timeExpire = DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 3);
            UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel()
                    .setAppid(appId)
                    .setMchid(wxPayV3Vo.getMchId())
                    .setDescription("在线购物")
                    .setOut_trade_no(output.getTradeNo())
                    .setTime_expire(timeExpire)
                    .setAttach(output.getTitle())
                    .setNotify_url(wxPayV3Vo.getDomain().concat("/front/pay/callback/wechatNotify"))
                    .setAmount(new Amount().setTotal(output.getAmount()))
                    .setPayer(new Payer().setOpenid(req.getOpenid()));

            logger.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));

            IJPayHttpResponse response = WxPayApi.v3(
                    RequestMethodEnum.POST,
                    WxDomainEnum.CHINA.toString(),
                    BasePayApiEnum.NATIVE_PAY.toString(),
                    wxPayV3Vo.getMchId(),
                    getSerialNumber(),
                    null,
                    wxPayV3Vo.getKeyPath(),
                    JSONUtil.toJsonStr(unifiedOrderModel)
            );

            logger.info("统一下单响应 {}", response);

            // 根据证书序列号查询对应的证书来验证签名结果
            boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Vo.getPlatformCertPath());

            logger.info("verifySignature: {}", verifySignature);

            if (response.getStatus() == 200 && verifySignature) {
                String body = response.getBody();
                cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(body);
                String codeUrl = jsonObject.getStr("code_url");
                wechatNativePayRes.setCodeUrl(codeUrl);

                return success(wechatNativePayRes);
            } else {
                LogUtil.error(ConstantLog.PAY, JSONUtil.toJsonStr(response));
            }

            wechatNativePayRes.setResponse(JSONUtil.toJsonStr(response));
            return fail(wechatNativePayRes);
        } catch (Exception e) {
            LogUtil.error(ConstantLog.PAY, e);
            return fail(wechatNativePayRes);
        }
    }

    @RequestMapping(value = "/wechatAppletPay", method = RequestMethod.POST)
    public CommonRes<WechatJSAPIPayRes> wechatAppletPay(PaymentReq req) {
        WxPayV3Vo wxPayV3Vo = configBaseService.getWxPayV3Vo();
        //weixin_app_id
        String appId = configBaseService.getConfig("wechat_xcx_app_id");
        wxPayV3Vo.setAppId(appId);

        req.setPaymentChannelId(StateCode.PAYMENT_CHANNEL_WECHAT);

        PaymentInput paymentInput = BeanUtil.copyProperties(req, PaymentInput.class);
        paymentInput.setOrderId(Convert.toList(String.class, req.getOrderId()));

        List<ConsumeTrade> consumeTrades = checkTrade(paymentInput);
        //订单id
        //是否为联合支付
        String tradeNo = combineRepository.getTradeNo(paymentInput.getOrderId());

        //标题
        List<String> titles = consumeTrades.stream().map(ConsumeTrade::getTradeTitle).collect(Collectors.toList());
        String title = CollUtil.join(titles, ",");

        //付款金额
        BigDecimal tradePaymentAmount = consumeTrades.stream().map(ConsumeTrade::getTradePaymentAmount).reduce(BigDecimal.ZERO, BigDecimal::add);

        WechatJSAPIPayRes wechatJSAPIPayRes = new WechatJSAPIPayRes();

        if (tradePaymentAmount.compareTo(BigDecimal.ZERO) <= 0) {
            wechatJSAPIPayRes.setPaid(true);
            //throw new BusinessException(__("无需支付！"));
        }

        wechatJSAPIPayRes.setOrderId(req.getOrderId());

        // 设置订单金额 单位为分且最小为1
        int amount = NumberUtil.mul(NumberUtil.round(tradePaymentAmount, 2), 100).intValue();

        try {
            String timeExpire = DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 3);
            UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel()
                    .setAppid(appId)
                    .setMchid(wxPayV3Vo.getMchId())
                    .setDescription(__("在线购物"))
                    .setOut_trade_no(tradeNo)
                    .setTime_expire(timeExpire)
                    .setAttach(title)
                    .setNotify_url(wxPayV3Vo.getDomain().concat("/front/pay/callback/wechatNotify"))
                    .setAmount(new Amount().setTotal(amount))
                    .setPayer(new Payer().setOpenid(req.getOpenid()));

            logger.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));

            IJPayHttpResponse response = WxPayApi.v3(
                    RequestMethodEnum.POST,
                    WxDomainEnum.CHINA.toString(),
                    BasePayApiEnum.JS_API_PAY.toString(),
                    wxPayV3Vo.getMchId(),
                    getSerialNumber(),
                    null,
                    wxPayV3Vo.getKeyPath(),
                    JSONUtil.toJsonStr(unifiedOrderModel)
            );

            logger.info("统一下单响应 {}", response);

            // 根据证书序列号查询对应的证书来验证签名结果
            boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Vo.getPlatformCertPath());

            logger.info("verifySignature: {}", verifySignature);

            if (response.getStatus() == 200 && verifySignature) {
                String body = response.getBody();
                cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(body);
                String prepayId = jsonObject.getStr("prepay_id");
                Map<String, String> map = WxPayKit.jsApiCreateSign(appId, prepayId, wxPayV3Vo.getKeyPath());
                wechatJSAPIPayRes.setData(map);

                return success(wechatJSAPIPayRes);
            } else {
                LogUtil.error(ConstantLog.PAY, JSONUtil.toJsonStr(response));
            }

            wechatJSAPIPayRes.setResponse(JSONUtil.toJsonStr(response));
            return fail(wechatJSAPIPayRes);
        } catch (Exception e) {
            LogUtil.error(ConstantLog.PAY, e);
            return fail(wechatJSAPIPayRes);
        }
    }

    @RequestMapping(value = "/wechatAppPay", method = RequestMethod.POST)
    public CommonRes<WechatAppPayRes> wechatAppPay(PaymentReq req) {
        req.setPaymentChannelId(StateCode.PAYMENT_CHANNEL_WECHAT);

        PayOutput output = getPayResult(req);

        //weixin_app_id
        String appId = configBaseService.getConfig("weixin_app_id");

        //商户编号
        String mchid = configBaseService.getConfig("wechat_pay_mchid");

        //密钥keyPath
        String keyPath = configBaseService.getConfig("wechat_pay_apiclient_key");

        //domain 项目域名
        String domain = ConstantConfig.URL_BASE;

        //微信平台证书
        File file = new File(getUploadFileDir(), "wx_cert.pem");
        String platformCertPath = file.getAbsolutePath();

        //App支付
        WechatAppPayRes wechatAppPayRes = new WechatAppPayRes();
        wechatAppPayRes.setOrderId(req.getOrderId());

        try {
            String timeExpire = DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 3);
            UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel()
                    .setAppid(appId)
                    .setMchid(mchid)
                    .setDescription("在线购物")
                    .setOut_trade_no(output.getTradeNo())
                    .setTime_expire(timeExpire)
                    .setAttach(output.getTitle())
                    .setNotify_url(domain.concat("/front/pay/callback/wechatNotify"))
                    .setAmount(new Amount().setTotal(output.getAmount()));
            logger.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));

            IJPayHttpResponse response = WxPayApi.v3(
                    RequestMethodEnum.POST,
                    WxDomainEnum.CHINA.toString(),
                    BasePayApiEnum.NATIVE_PAY.toString(),
                    mchid,
                    getSerialNumber(),
                    null,
                    keyPath,
                    JSONUtil.toJsonStr(unifiedOrderModel)
            );
            logger.info("统一下单响应 {}", response);
            // 根据证书序列号查询对应的证书来验证签名结果
            boolean verifySignature = WxPayKit.verifySignature(response, platformCertPath);
            logger.info("verifySignature: {}", verifySignature);
            if (response.getStatus() == 200 && verifySignature) {
                String body = response.getBody();
                cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(body);
                String prepayId = jsonObject.getStr("prepay_id");
                Map<String, String> map = WxPayKit.appCreateSign(appId, mchid, prepayId, keyPath);
                wechatAppPayRes.setData(map);
                logger.info("唤起支付参数:{}", map);
                return success(wechatAppPayRes);
            } else {
                LogUtil.error(ConstantLog.PAY, JSONUtil.toJsonStr(response));
            }

            wechatAppPayRes.setResponse(JSONUtil.toJsonStr(response));
            return fail(wechatAppPayRes);
        } catch (Exception e) {
            LogUtil.error(ConstantLog.PAY, e);
            return fail(wechatAppPayRes);
        }
    }

    private List<ConsumeTrade> checkTrade(PaymentInput input) {
        QueryWrapper<ConsumeTrade> tradeQueryWrapper = new QueryWrapper<>();
        tradeQueryWrapper.in("order_id", input.getOrderId());
        List<ConsumeTrade> consumeTrades = tradeRepository.find(tradeQueryWrapper);

        if (CollectionUtil.isEmpty(consumeTrades)) {
            throw new BusinessException(__("交易订单不存在"));
        }

        //判断是否可以联合支付

        //是否包含已付款
        List<Integer> isPaidList = consumeTrades.stream().map(ConsumeTrade::getTradeIsPaid).collect(Collectors.toList());
        if (isPaidList.contains(StateCode.ORDER_PAID_STATE_YES)) {
            throw new BusinessException(__("存在订单状态不为待付款状态！"));
        }

        return consumeTrades;
    }

    /**
     * 获取证书序列号
     */
    private String getSerialNumber() {
        //证书序列号
        String serialNo = configBaseService.getConfig("wechat_pay_serial_no");

        if (StrUtil.isEmpty(serialNo)) {
            //这个是证书文件，后续要调整成读取证书文件的服务器存放地址  微信支付证书
            String cert = configBaseService.getConfig("wechat_pay_apiclient_cert");

            if (cert != null) {
                // 获取证书序列号
                X509Certificate certificate = PayKit.getCertificate(cert);
                if (certificate != null) {
                    serialNo = certificate.getSerialNumber().toString(16).toUpperCase();
                }
            }
        }

        return serialNo;
    }

    @RequestMapping(value = "/wechatJSAPIPay", method = RequestMethod.POST)
    public CommonRes<WechatJSAPIPayRes> wechatJSAPIPay(PaymentReq req) {
        WxPayV3Vo wxPayV3Vo = configBaseService.getWxPayV3Vo();
        //weixin_app_id
        String appId = configBaseService.getConfig("wechat_app_id");
        wxPayV3Vo.setAppId(appId);

        req.setPaymentChannelId(StateCode.PAYMENT_CHANNEL_WECHAT);

        PayOutput output = getPayResult(req);

        Integer userId = ContextUtil.getLoginUserId();
        QueryWrapper<UserBindConnect> connectQueryWrapper = new QueryWrapper<>();
        connectQueryWrapper.eq("user_id", userId).eq("bind_type", BindConnectCode.WEIXIN);
        UserBindConnect bindConnect = userBindConnectRepository.findOne(connectQueryWrapper);
        if (bindConnect == null || StrUtil.isEmpty(bindConnect.getBindOpenid())) {
            throw new BusinessException(__("当前账号非微信渠道注册！"));
        }

        req.setOpenid(bindConnect.getBindOpenid());

        WechatJSAPIPayRes wechatJSAPIPayRes = new WechatJSAPIPayRes();
        wechatJSAPIPayRes.setOrderId(req.getOrderId());

        try {
            String timeExpire = DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 3);
            UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel()
                    .setAppid(appId)
                    .setMchid(wxPayV3Vo.getMchId())
                    .setDescription("在线购物")
                    .setOut_trade_no(output.getTradeNo())
                    .setTime_expire(timeExpire)
                    .setAttach(output.getTitle())
                    .setNotify_url(wxPayV3Vo.getDomain().concat("/front/pay/callback/wechatNotify"))
                    .setAmount(new Amount().setTotal(output.getAmount()))
                    .setPayer(new Payer().setOpenid(req.getOpenid()));

            logger.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));

            IJPayHttpResponse response = WxPayApi.v3(
                    RequestMethodEnum.POST,
                    WxDomainEnum.CHINA.toString(),
                    BasePayApiEnum.JS_API_PAY.toString(),
                    wxPayV3Vo.getMchId(),
                    getSerialNumber(),
                    null,
                    wxPayV3Vo.getKeyPath(),
                    JSONUtil.toJsonStr(unifiedOrderModel)
            );

            logger.info("统一下单响应 {}", response);

            // 根据证书序列号查询对应的证书来验证签名结果
            boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Vo.getPlatformCertPath());

            logger.info("verifySignature: {}", verifySignature);

            if (response.getStatus() == 200 && verifySignature) {
                String body = response.getBody();
                cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(body);
                String prepayId = jsonObject.getStr("prepay_id");
                Map<String, String> map = WxPayKit.jsApiCreateSign(appId, prepayId, wxPayV3Vo.getKeyPath());
                wechatJSAPIPayRes.setData(map);

                return success(wechatJSAPIPayRes);
            } else {
                LogUtil.error(ConstantLog.PAY, JSONUtil.toJsonStr(response));
            }

            wechatJSAPIPayRes.setResponse(JSONUtil.toJsonStr(response));
            return fail(wechatJSAPIPayRes);
        } catch (Exception e) {
            LogUtil.error(ConstantLog.PAY, e);
            return fail(wechatJSAPIPayRes);
        }
    }


    @RequestMapping(value = "/wechatH5Pay", method = RequestMethod.POST)
    public CommonRes<WechatJSAPIPayRes> wechatH5Pay(PaymentReq req) {
        WxPayV3Vo wxPayV3Vo = configBaseService.getWxPayV3Vo();
        //weixin_app_id
        String appId = configBaseService.getConfig("wechat_app_id");
        wxPayV3Vo.setAppId(appId);

        req.setPaymentChannelId(StateCode.PAYMENT_CHANNEL_WECHAT);

        PayOutput output = getPayResult(req);

        WechatJSAPIPayRes wechatJSAPIPayRes = new WechatJSAPIPayRes();
        wechatJSAPIPayRes.setOrderId(req.getOrderId());

        try {
            String timeExpire = DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 3);

            H5Info h5Info = new H5Info();
            h5Info.setType("Wap");
            h5Info.setApp_url(ConstantConfig.URL_BASE);
            h5Info.setApp_name("随商商城");
            SceneInfo sceneInfo = new SceneInfo();
            sceneInfo.setPayer_client_ip(HttpServletUtils.getClientIpAddr());
            sceneInfo.setH5_info(h5Info);

            UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel()
                    .setAppid(appId)
                    .setMchid(wxPayV3Vo.getMchId())
                    .setDescription("在线购物")
                    .setOut_trade_no(output.getTradeNo())
                    .setTime_expire(timeExpire)
                    .setAttach(output.getTitle())
                    .setNotify_url(wxPayV3Vo.getDomain().concat("/front/pay/callback/wechatNotify"))
                    .setAmount(new Amount().setTotal(output.getAmount()))
                    .setScene_info(sceneInfo)
                    .setPayer(new Payer().setOpenid(req.getOpenid()));

            logger.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));

            IJPayHttpResponse response = WxPayApi.v3(
                    RequestMethodEnum.POST,
                    WxDomainEnum.CHINA.toString(),
                    BasePayApiEnum.H5_PAY.toString(),
                    wxPayV3Vo.getMchId(),
                    getSerialNumber(),
                    null,
                    wxPayV3Vo.getKeyPath(),
                    JSONUtil.toJsonStr(unifiedOrderModel)
            );

            logger.info("统一下单响应 {}", response);

            // 根据证书序列号查询对应的证书来验证签名结果
            boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Vo.getPlatformCertPath());

            logger.info("verifySignature: {}", verifySignature);

            if (response.getStatus() == 200 && verifySignature) {
                String body = response.getBody();
                cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(body);
                String mwebUrl = jsonObject.getStr("h5_url");
                String prepayId = jsonObject.getStr("prepay_id");
                Map<String, String> map = WxPayKit.jsApiCreateSign(appId, prepayId, wxPayV3Vo.getKeyPath());
                wechatJSAPIPayRes.setMwebUrl(mwebUrl);
                wechatJSAPIPayRes.setData(map);

                return success(wechatJSAPIPayRes);
            } else {
                LogUtil.error(ConstantLog.PAY, JSONUtil.toJsonStr(response));
            }

            wechatJSAPIPayRes.setResponse(JSONUtil.toJsonStr(response));
            return fail(wechatJSAPIPayRes);
        } catch (Exception e) {
            LogUtil.error(ConstantLog.PAY, e);
            return fail(wechatJSAPIPayRes);
        }
    }

    @RequestMapping(value = "/alipayPay", method = RequestMethod.POST)
    public CommonRes<AliPayRes> alipayPay(PaymentReq req) {
        return getAliPayResCommonRes(req, PayType.ALIPAY_H5);
    }

    @RequestMapping(value = "/alipayPcPay", method = RequestMethod.POST)
    public CommonRes<AliPayRes> alipayPcPay(PaymentReq req) {
        return getAliPayResCommonRes(req, PayType.ALI_PC_PAY);
    }

    /**
     * 获取支付宝支付返回信息
     *
     * @param req
     * @param payType
     * @return
     */
    private CommonRes<AliPayRes> getAliPayResCommonRes(PaymentReq req, PayType payType) {
        AliPayVo aliPayVo = configBaseService.getAliPayVo();

        req.setPaymentChannelId(StateCode.PAYMENT_CHANNEL_ALIPAY);

        PayOutput output = getPayResult(req);

        String returnUrl = aliPayVo.getReturnUrl();
        String notifyUrl = aliPayVo.getNotifyUrl();

        String body = ObjectUtil.defaultIfBlank(output.getTitle(), output.getTradeNo());

        try {
            AlipayTradeWapPayModel parameter = new AlipayTradeWapPayModel();
            parameter.setSubject(output.getTitle());
            parameter.setOutTradeNo(output.getTradeNo());
            parameter.setBody(body);
            BigDecimal amount = NumberUtil.div(new BigDecimal(output.getAmount()), new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP);
            parameter.setTotalAmount(amount.toString());
            parameter.setProductCode("FAST_INSTANT_TRADE_PAY");

            AlipayRequest<?> aliPayRequest;
            if (payType.equals(PayType.ALIPAY_H5)) {
                aliPayRequest = new AlipayTradeWapPayRequest();
            } else if (payType.equals(PayType.ALI_PC_PAY)) {
                aliPayRequest = new AlipayTradePagePayRequest();
            } else {
                throw new BusinessException(ResultCode.VALIDATE_FAILED);
            }

            aliPayRequest.setReturnUrl(returnUrl);
            aliPayRequest.setNotifyUrl(notifyUrl);
            aliPayRequest.setBizModel(parameter);
            String mwebUrl = AliPayApi.pageExecute(aliPayRequest, "GET").getBody();

            AliPayRes res = new AliPayRes();
            res.setMwebUrl(mwebUrl);
            res.setOrderId(output.getTradeNo());
            res.setStatusCode(200);
            res.setPaid(false);
            return success(res);
        } catch (Exception e) {
            LogUtil.error(ErrorTypeEnum.ERR_ALI_PAY.getValue(), e);
            throw new BusinessException(__("支付宝支付失败！"));
        }
    }

    /**
     * 获取业务返回数据
     *
     * @param req
     * @return
     */
    @NotNull
    private PayOutput getPayResult(PaymentReq req) {
        PaymentInput paymentInput = BeanUtil.copyProperties(req, PaymentInput.class);
        paymentInput.setOrderId(Convert.toList(String.class, req.getOrderId()));

        List<ConsumeTrade> consumeTrades = checkTrade(paymentInput);
        //订单id
        //是否为联合支付
        String tradeNo = combineRepository.getTradeNo(paymentInput.getOrderId());

        //标题
        List<String> titles = consumeTrades.stream().map(ConsumeTrade::getTradeTitle).collect(Collectors.toList());
        String title = CollUtil.join(titles, ",");

        //付款金额
        BigDecimal tradePaymentAmount = consumeTrades.stream().map(ConsumeTrade::getTradePaymentAmount).reduce(BigDecimal.ZERO, BigDecimal::add);

        if (tradePaymentAmount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessException(__("无需支付！"));
        }
        // 设置订单金额 单位为分且最小为1
        int amount = NumberUtil.mul(NumberUtil.round(tradePaymentAmount, 2), 100).intValue();
        return new PayOutput(tradeNo, title, amount);
    }

    @RequestMapping(value = "/niHaoPayCallback", method = RequestMethod.POST)
    public CommonRes<?> niHaoPayCallback(HttpServletRequest request, HttpServletResponse response)  throws ServletException, IOException {

        PaymentReq req = new PaymentReq();
        String id = request.getParameter("id");
        String status = request.getParameter("status");
        String currency = request.getParameter("currency");
        String amount = request.getParameter("amount");
        Integer rmb_amount = Integer.valueOf(request.getParameter("rmb_amount"));
        String time = request.getParameter("time");
        String reference = request.getParameter("reference");
        String note = request.getParameter("note");

        String sys_reserve = request.getParameter("sys_reserve");
        //JSONObject refundObj = JSONUtil.parseObj(sys_reserve);
        String verify_sign = request.getParameter("verify_sign");
//
//        System.out.println("id: " + id);
//        System.out.println("status: " + status);
//        System.out.println("currency: " + currency);
//        System.out.println("amount: " + amount);
//        System.out.println("rmb_amount: " + rmb_amount);
//        System.out.println("time: " + time);
//        System.out.println("reference: " + reference);
//        System.out.println("note: " + note);
//        System.out.println("sys_reserve: " + sys_reserve);
//        //System.out.println("refundObj: " + refundObj);
//        System.out.println("verify_sign: " + verify_sign);

        //回调后的金额转BigDecimal
        BigDecimal bigDecimalValue = new BigDecimal(rmb_amount);
        req.setOrderId(reference);

        MoneyPayRes res = new MoneyPayRes();
        res.setOrderId(req.getOrderId());
        // 处理回调数据
        if("success".equals(status)){
            req.setPaymentChannelId(StateCode.PAYMENT_NI_HAO);
            req.setDepositPaymentType(StateCode.PAYMENT_TYPE_ONLINE);
            //处理订单支付结果
            PayMetVo payInfo = new PayMetVo();
            //微信/支付宝
            payInfo.setPaymentMetId(StateCode.PAYMENT_NI_HAO);

            payInfo.setPaymentChannelId(req.getPaymentChannelId());
            payInfo.setPaymentTypeId(req.getDepositPaymentType());
            payInfo.setPmMoney(bigDecimalValue.divide(BigDecimal.valueOf(100),2,BigDecimal.ROUND_HALF_UP));
            //处理订单逻辑
            ProcessPayOutput processPayOutput = consumeTradeService.nihaoProcessPay(req.getOrderId(), payInfo);

            if (processPayOutput.getPaid()) {

                res.setPaid(processPayOutput.getPaid());
                res.setStatusCode(200);
                // 响应 "ok" 给Nihaopay服务
                response.setStatus(HttpServletResponse.SC_OK);
                // 获取输出流，并写入"ok"
                response.getOutputStream().print("ok");
            } else {
                System.out.println("--------处理逻辑出错了------" );
                res.setStatusCode(250);
            }
            return success(res);
        } else {
            res.setPaid(false);
            res.setStatusCode(250);
            return fail(res);
        }

    }

    @ResponseBody
    @RequestMapping(value = "/niHaoPay", method = RequestMethod.POST)
    public HashMap<String,String> niHaoPay( PaymentReq req) throws IOException {
        HashMap<String,String> map = new HashMap<>();
        String token = "816151c8f7520ccff745c169e2c95fd8dce8c29dbe338d079d9090174641e1f0";
        String url = "https://api.nihaopay.com/v1.2/transactions/securepay";
        String callback_url = "https://www.haioushop.com/member/order/detail?on="+req.getOrderId();
        String ipn_url = "https://www.haioushop.com/front/pay/consumeDeposit/niHaoPayCallback?on="+req.getOrderId();
        BigDecimal hs =new BigDecimal(100);
        String ip = HttpServletUtils.getClientIpAddr();

        BigDecimal rmb_amount=req.getPmMoney().multiply(hs).setScale(0, RoundingMode.DOWN);
        String param ="currency=HKD&clientIp="+ip+"&vendor="+req.getVendor()+"&reference="+req.getOrderId()+"&ipn_url="+ipn_url+"&callback_url="+callback_url+"&terminal=WAP";
        String data = param+"&rmb_amount="+rmb_amount;
        URL obj = new URL(url);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();
        con.setRequestMethod("POST");
        con.setRequestProperty("Authorization", "Bearer " + token);
        con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        con.setDoOutput(true);
        DataOutputStream wr = new DataOutputStream(con.getOutputStream());
        wr.writeBytes(data);
        wr.flush();
        wr.close();
//        System.out.println("data: " + data.toString());
//        int responseCode = con.getResponseCode();
//        System.out.println("Response Code : " + responseCode);
        BufferedReader in = new BufferedReader(
                new InputStreamReader(con.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();
//        System.out.println("回调成功后html: " + response.toString());
//        System.out.println("回调地址callback_url: " + callback_url);

        map.put("data",response.toString());
        return map;

    }

    @ResponseBody
    @RequestMapping(value = "/productPay", method = RequestMethod.POST)
    public CommonRes<?> productPay(PaymentReq req) throws IOException {
        // 1.组装支付初始化参数
        JSONObject payJson = new JSONObject();
        //返回结果集
        JSONObject json = new JSONObject();
        //接口类型
        payJson.put("service", req.getVendor());
        //商品描述：无格式要求，暂定为：提交订单+订单号
        payJson.put("body","Hong Kong");
        //编码
        //payJson.put("charset","UTF-8");
        //商户号
        payJson.put("mch_id",ConstantPay.MERCHANT_CD);
        //随机32位id添加至json对象
        payJson.put("nonce_str", UUID.randomUUID().toString().replace("-",""));
        //订单号
        payJson.put("out_trade_no",req.getOrderId());
        //终端ip添加至json对象
        payJson.put("mch_create_ip", InetAddress.getLocalHost().getHostAddress());
        //终端ip添加至json对象
        payJson.put("payer_client_ip", InetAddress.getLocalHost().getHostAddress());
        //订单金额
        BigDecimal inv = new BigDecimal("100");
        payJson.put("total_fee",(req.getPmMoney().multiply(inv)).intValue());
        /**订单支付成功回调接口*/
        String NOTIFY_URL = "https://test.haioushop.com/front/pay/consumeDeposit/paymentCallback";
        payJson.put("notify_url",NOTIFY_URL);
        //生成签名,添加至json对象
        String sign = md5Password(generateSignBlockString(payJson)+"&key="+ ConstantPay.PAYMENT_KEY).toUpperCase();
        payJson.put("sign", sign);
        //发起订单支付
        json =sendPayment(payJson);
        return success(json);

    }
    /**
     *  发起订单，初始化接口
     * @author: drx
     * @date: 2023/5/8 15:47
     * @param: jsonObject 初始化参数对象
     * @return: JSONObject 成功/失败
     **/
    public JSONObject sendPayment(JSONObject jsonObject){
        JSONObject json = new JSONObject();
        try {
            URL url = new URL(ConstantPay.PAY_URL);
            //支付路由
//            if(ConstantPay.SERVICE_NATIVE.equals(jsonObject.get("service")) ){
//                url = new URL(ConstantPay.PAY_WX_URL);
//            }else{
//                url = new URL(ConstantPay.PAY_URL);
//            }

            URLConnection con = url.openConnection();
            con.setDoOutput(true);
            //Wcon.setRequestProperty("Pragma:", "no-cache");
            con.setRequestProperty("Cache-Control", "no-cache");
            con.setRequestProperty("Content-Type", "text/xml");
            OutputStreamWriter out = new OutputStreamWriter(con.getOutputStream());

            //组装xml
            String xmlStr = JsonToXmlUtils.json2xml(jsonObject);
            xmlStr = "<xml>" + xmlStr + "</xml>";
            System.out.println("------------请求报文---------:"+xmlStr.toString());
            out.write(new String(xmlStr.toString().getBytes("UTF-8")));
            out.flush();
            out.close();
            BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
            //返回xml字符串
            String line = "";
            StringBuffer lineBf = new StringBuffer();
            //循环拼接xml字符串
            for (line = br.readLine(); line != null; line = br.readLine()) {
                lineBf.append(line);
            }
            line = lineBf.toString();
            System.out.println("1----:"+line.toString());

            //xml字符串转json
            json = XmltoJsonUtils.xmltoJson(line);
            System.out.println("2----:"+json.toString());
            json.put("msg","调取支付操作成功！");
            return json;
        } catch (Exception e) {
            e.printStackTrace();
            json.put("msg","调取支付操作失败！");
            return json;
        }
    }
    @ResponseBody
    @RequestMapping(value = "/paymentCallback", method = RequestMethod.POST)
    public String paymentCallback(HttpServletRequest req, HttpServletResponse resp) {
        String respString = "fail";

        try {
            PaymentReq payReq = new PaymentReq();

            //MoneyPayRes monRes = new MoneyPayRes();
            req.setCharacterEncoding("utf-8");
            resp.setCharacterEncoding("utf-8");
            resp.setHeader("Content-type", "text/html;charset=UTF-8");
            String resString = XmlUtils.parseRequst(req);
            if (resString != null && !"".equals(resString)) {
                Map<String, String> map = XmlUtils.toMap(resString.getBytes(), "utf-8");
                String res = XmlUtils.toXml(map);
                System.out.println("通知内容res：" + res);
                if (map.containsKey("sign")) {
                    if (!SignUtils.checkParam(map, ConstantPay.PAYMENT_KEY)) {
                        res = "验证签名不通过";
                        respString = "fail";
                        return respString;
                    } else {
                        String status = map.get("status");
                        if (status != null && "0".equals(status)) {
                            String result_code = map.get("result_code");
                            if (result_code != null && "0".equals(result_code)) {
                                //resp.getOutputStream().print("ok");
                                payReq.setOrderId(map.get("out_trade_no"));

                                payReq.setPaymentChannelId(StateCode.PAYMENT_NI_HAO);
                                payReq.setDepositPaymentType(StateCode.PAYMENT_TYPE_ONLINE);
                                //处理订单支付结果
                                PayMetVo payInfo = new PayMetVo();
                                //微信/支付宝
                                payInfo.setPaymentMetId(StateCode.PAYMENT_NI_HAO);
                                payInfo.setPaymentChannelId(payReq.getPaymentChannelId());
                                payInfo.setPaymentTypeId(payReq.getDepositPaymentType());
                                payInfo.setPmMoney(BigDecimal.valueOf(Integer.valueOf(map.get("total_fee"))).divide(BigDecimal.valueOf(100),2,BigDecimal.ROUND_HALF_UP));
                                System.out.println("--------存库的钱------：" + payInfo.getPmMoney());
                                //处理订单逻辑
                                ProcessPayOutput processPayOutput = consumeTradeService.nihaoProcessPay(payReq.getOrderId(), payInfo);
                                System.out.println("--------处理成功了------");
                                if (processPayOutput.getPaid()) {
                                    System.out.println("--------直接完事------");
                                    respString = "success";
                                    resp.getOutputStream().print(respString);
                                    //resp.getWriter().write(respString);
                                   return respString;
                                } else {
                                    System.out.println("--------处理逻辑出错了------");
                                    respString = "fail";
                                    resp.getOutputStream().print(respString);
                                    return respString;
                                }
                            }
                        }
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return respString;
    }

    /**
     * 回调业务处理
     * @author: drx
     * @date: 2023/5/10 15:37
     * @param: orderNum 订单号
     * @return:
     **/
    @GetMapping(value = "/callbackBusiness/{orderId}")
    public String callbackBusiness(@PathVariable("orderId")String orderId) {
        //返回状态
        String respString = "";
        PaymentReq req = new PaymentReq();
        req.setOrderId(orderId);
        MoneyPayRes res = new MoneyPayRes();
        req.setPaymentChannelId(StateCode.PAYMENT_NI_HAO);
        req.setDepositPaymentType(StateCode.PAYMENT_TYPE_ONLINE);
        //处理订单支付结果
        PayMetVo payInfo = new PayMetVo();
        //微信/支付宝
        payInfo.setPaymentMetId(StateCode.PAYMENT_NI_HAO);
        payInfo.setPaymentChannelId(req.getPaymentChannelId());
        payInfo.setPaymentTypeId(req.getDepositPaymentType());
        payInfo.setPmMoney(BigDecimal.valueOf(6));
        System.out.println("--------存库的钱------："+payInfo.getPmMoney() );
        //处理订单逻辑
        ProcessPayOutput processPayOutput = consumeTradeService.nihaoProcessPay(req.getOrderId(), payInfo);
        System.out.println("--------处理成功了------" );
        if (processPayOutput.getPaid()) {
            System.out.println("--------直接完事------" );
            res.setPaid(processPayOutput.getPaid());
            res.setStatusCode(200);
            respString = "success";
        } else {
            System.out.println("--------处理逻辑出错了------" );
            respString = "fail";
        }
        return respString;
    }

    /**
     * 生成签名（ascii 碼從小到大排序後使用 QueryString 的格式）
     * （即 key1=value1&key2=value2…）拼接而成，空值不傳遞，不參與簽名組串
     * @author: drx
     * @date: 2023/5/8 15:34
     * @param: jsonObject 参数json对象
     * @return: String (url串key1=value1&key2=value2…)
     **/
    private String generateSignBlockString(JSONObject jsonObject) {
        try {
            Map maps = jsonObject.getInnerMap();
            ArrayList<String> arrayList = new ArrayList<>();
            int i = 0;
            Object key;
            Object value;
            for (Object map : maps.entrySet()) {
                key = ((Map.Entry) map).getKey();
                value = ((Map.Entry) map).getValue();
                if(null != value){
                    arrayList.add(key + "=" + value + "&");//使用URL键值对的格式（key1=value1&key2=value2…）拼接成字符串sign。
                }
                i++;
            }
            String[] strArray = arrayList.toArray(new String[arrayList.size()]);
            Arrays.sort(strArray);
            StringBuffer stringBuffer = new StringBuffer();
            for (i = 0; i < strArray.length; i++) {
                stringBuffer.append(strArray[i]);
            }
            return stringBuffer.substring(0, stringBuffer.length() - 1).toString();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 生成32位md5码
     *
     * @param key
     * @return
     */
    public static String md5Password(String key) {
        char hexDigits[] = {
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
        };
        try {
            byte[] btInput = key.getBytes();
            // 得到MD5摘要算法的 MessageDigest 对象
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            // 使用指定的字节更新摘要
            mdInst.update(btInput);
            // 得到密文
            byte[] md = mdInst.digest();
            // 把密文转换成十六进制的字符串形式
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            return null;
        }
    }
}

